package com.wbsxch.secondkill.service.impl;

import com.wbsxch.secondkill.dto.Exposer;
import com.wbsxch.secondkill.dto.SecondKillExecution;
import com.wbsxch.secondkill.entity.SecondKill;
import com.wbsxch.secondkill.entity.SuccessKilled;
import com.wbsxch.secondkill.enums.SecondKillStateEnum;
import com.wbsxch.secondkill.exception.RepeatKillException;
import com.wbsxch.secondkill.exception.SecondKillCloseException;
import com.wbsxch.secondkill.exception.SecondKillException;
import com.wbsxch.secondkill.mapper.SecondKillMapper;
import com.wbsxch.secondkill.mapper.SuccessKilledMapper;
import com.wbsxch.secondkill.service.SecondKillService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;

import java.util.Date;
import java.util.List;

@Service
public class SecondKillServiceImpl implements SecondKillService {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    private final String salt = "sadkfjalsdjfalksj23423^&*^&%&!EBJKH#e™£4";

    @Autowired
    private SecondKillMapper secondKillMapper;

    @Autowired
    private SuccessKilledMapper successKilledMapper;

    @Override
    public List<SecondKill> selectAll() {
        return secondKillMapper.queryAll(0,10);
    }

    @Override
    public SecondKill selectById(long secondKillId) {
        return secondKillMapper.queryById(secondKillId);
    }

    @Override
    public Exposer exportSecondKillUrl(long secondKillId) {
        SecondKill secondKill = this.selectById(secondKillId);
        if(secondKill == null){
            return new Exposer(false,secondKillId);
        }

        long startTime = secondKill.getStartTime().getTime();
        long endTime = secondKill.getEndTime().getTime();
        long now = System.currentTimeMillis();
        if(now < startTime || now > endTime){
            return new Exposer(false,secondKillId,now,startTime,endTime);
        }
        String md5 = getMD5(secondKillId);
        return new Exposer(true,md5,secondKillId);
    }

    private String getMD5(long secondKillId){
        String base = secondKillId + "/" + salt;
        return DigestUtils.md5DigestAsHex(base.getBytes());
    }

    @Override
    @Transactional
    public SecondKillExecution executeSecondKill(long secondKillId, long phone, String md5) throws Exception, RepeatKillException, SecondKillCloseException {
        if(md5 == null || !md5.equals(getMD5(secondKillId))){
            throw new SecondKillException("数据被重写");
        }
        try {
            //减库存
            Date now = new Date();
            int updateCount = secondKillMapper.reduceNumber(secondKillId, now);
            if(updateCount <= 0){
                throw new SecondKillCloseException("秒杀关闭");
            }else{
                //记录秒杀行为
                int insertCount = successKilledMapper.insertSuccessKilled(secondKillId, phone);
                if(insertCount <= 0){
                    throw new RepeatKillException("重复秒杀");
                }else {
                    SuccessKilled successKilled = successKilledMapper.queryByIdWithSecondKill(secondKillId, phone);
                    return new SecondKillExecution(secondKillId,SecondKillStateEnum.SUCCESS,successKilled);
                }
            }
        } catch (SecondKillException e1) {
            throw e1;
        } catch (SecondKillCloseException e2) {
            throw e2;
        } catch (Exception e3) {
            logger.error(e3.getMessage(), e3);
            throw new SecondKillException("inner error:" + e3.getMessage());
        }

    }
}
